home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 037a / wedits22.zip / WWIVEDIT.PAS < prev    next >
Pascal/Delphi Source File  |  1991-08-19  |  30KB  |  1,138 lines

  1. {$M 16000,0,655360}
  2. PROGRAM WWIVEdit(Input,Output);
  3. (******************************************************************************
  4.  **                                                                          **
  5.  **                             WWIVEdit Version 2.2                         **
  6.  **                            Last Modified : 8/19/91                       **
  7.  **                        By Adam Caldwell (The Emporer)                    **
  8.  **               1@ 16401 (Link) [The First Galactic Empire (Link)]         **
  9.  **               1@  6470 (Net)  [The First Galactic Empire (Net) ]         **
  10.  **             718@  5252 (Net)  [Dragon's Den (Net)              ]         **
  11.  **                      Phone: (614) 593-7836 [ Link BBS ]                  **
  12.  **                                                                          **
  13.  ** Purpose : WWIV is a full screen editor designed specifically for use with**
  14.  ** the WWIV 4.xx BBS system.  It takes advantage of many of the features    **
  15.  ** features of WWIV such as colors, Macros, and WWIV specific formatting    **
  16.  ** functions.                                                               **
  17.  ** It is a Word Processor like editor that I have written to be             **
  18.  ** easily Extendable (if you understand my programming style :-)            **
  19.  **                                                                          **
  20.  ** This source code is Limited Public Domain.  By this I mean that you may  **
  21.  ** freely modify and distribute this source code so long as:                **
  22.  **    1) No Fee is charged for this or any product derived from this code   **
  23.  **    2) Any modifications that you make are CLEARLY noted as not being     **
  24.  **       my code (ie, initial it) if you distrubute modified versions       **
  25.  **    3) You don't change this message header in any way [including removal **
  26.  **       of it]                                                             **
  27.  **    4) No NOT use the naming convention WEDITSxx.ZIP when distributing it **
  28.  **       This is reserved for *official* releases                           **
  29.  **                                                                          **
  30.  ******************************************************************************)
  31.  
  32. {{$DEFINE DEBUG}       { Remove first comment symbol to make actually define it }
  33. {{$DEFINE DIRECTVIDEO} { Don't define either of these for the BBS }
  34. {$DEFINE OVERLAY}      { UnDefine if you don't want overlays }
  35. {$DEFINE VERSION_2_2}  { Doesn't do anything... Just there so you know what version it is }
  36.  
  37. {$IFDEF DEBUG}
  38. {$R+,V+,S+,B-,E-,N-}   { These were used to find a bunch of little bugs :-)  }
  39. {$ELSE}
  40. {$R-,V-,S-,B-,E-,N-}   { These Optomize things as much as possible }
  41. {$ENDIF}
  42.  
  43. USES DOS, WEMisc,WEVars, WEDict, WEKbd, WETime, WEString,
  44.      WELine, WEOutput, WEChat, WEInit, WEInput, WETag{, WEDefaul}
  45.  
  46. {$IFDEF OVERLAY}
  47.      ,Overlay
  48. {$ENDIF}
  49.  
  50. {$IFDEF DIRECTVIDEO} {-- This unit uses the CRT unit.  I wrote this because I needed}
  51.      ,WWIVOutp       {-- to debug this code on a system without an ANSI driver.}
  52. {$ENDIF};            {-- It is also used to "simulate" 12/2400 bps modems... Available upon request }
  53.  
  54. {$IFDEF OVERLAY}
  55.   {$O WEChat}
  56.   {$O WEDict}
  57.   {$O WEInit}
  58.   {$O WETag}
  59.   {$O WEMisc}
  60.   {{$O WEDefaul}   { ** Future Enhancement ** }
  61. {$ENDIF}
  62.  
  63. PROCEDURE ScrollWindowDown;
  64. { Moves the viewport down on the Text Buffer }
  65. VAR x:integer;
  66. BEGIN
  67.   IF cy>MaxLines THEN cy:=MaxLines-1;
  68.   x:=cy-ViewTop;
  69.   cy:=cy+WindowHeight-MinScrollLeft;
  70.   ViewTop:=cy-x;
  71.   ViewBottom:=ViewTop + WindowHeight;
  72.   IF viewBottom>MaxLines THEN BEGIN
  73.     ViewBottom:=MaxLines-1;
  74.     ViewTop:=ViewTop-WindowHeight;
  75.     cy:=ViewBottom;
  76.   END;
  77. END;
  78.  
  79.  
  80.  
  81. PROCEDURE ScrollWindowUp;
  82. VAR x:integer;
  83. { Moves the Viewport Up on the Text Buffer }
  84. BEGIN
  85.   IF cy<1 THEN cy:=1;
  86.   x:=cy-ViewTop;
  87.   cy:=cy-WindowHeight+MinScrollLeft;
  88.   ViewTop:=cy-x;
  89.   ViewBottom:=ViewTop+WindowHeight;
  90.   IF ViewTop<1 THEN BEGIN
  91.     ViewTop:=1;
  92.     cy:=1;
  93.     ViewBottom:=ViewTop + WindowHeight;
  94.   END;
  95. END;
  96.  
  97.  
  98.  
  99.  
  100. FUNCTION Done(VAR Cmd:EdFun):boolean;
  101. { Asks whether or not user wants to save, Abort, or Resume, and handles
  102.   calls to EditTagline }
  103. VAR
  104.   ch:char;
  105.   OkSet : CharSet;
  106.   TagS:string;
  107.   TagCh:string;
  108. BEGIN
  109.   Ansic('0');
  110.   OkSet:=['A','S','R','D',ESC];
  111.   IF NOT (Cmd IN [AbortPost,QuietExitAndSave]) THEN
  112.   BEGIN
  113.     IF OkTagLines THEN BEGIN
  114.       TagS:=', '+C1+'T'+C2+'aglines';
  115.       OkSet:=OkSet+['T'];
  116.       TagCh:='T'
  117.     END ELSE BEGIN
  118.       TagS:='';
  119.       TagCh:=''
  120.     END;
  121.     StatusLine3(C1+'A'+C2+'bort, '+C1+'S'+C2+'ave, '+C1+'R'+C2+'esume'+
  122.                 {C1+'D'+C2+'efaults'}+TagS+' [ASR'+TagCh+'] > '+C1);
  123.     IF Cmd=ExitAndSave
  124.       THEN ch:='S'
  125.       ELSE ch:=ReadSet(OkSet);
  126.     IF ch=#27 THEN ch:='R';
  127.     ansic('0');
  128.     IF ch='A' THEN
  129.     BEGIN
  130.       gotoxy(6,WindowBottom+1);
  131.       clreol;
  132.       prompt('   '+C6+'Are you sure?'+C2+' [yN] '+C1);
  133.       ch:=ReadSet(['Y','N',ENTERKey,ESC]);
  134.       IF ch <>'Y'
  135.         THEN ch:='R'
  136.         ELSE ch:='A'
  137.     END;
  138.     IF ch='R' THEN
  139.     BEGIN
  140.       StatusLine3('');
  141.       ShowMaxLines
  142.     END
  143.     ELSE IF Ch='T' THEN
  144.     BEGIN
  145.       EditTaglines;
  146.       ForcedRedisplay;
  147.     END {
  148.     ELSE IF ch='D' THEN
  149.     BEGIN
  150.       EditDefaults;
  151.       ForcedRedisplay;
  152.     END};
  153.     Done:=ch IN ['S','A'];
  154.     IF ch ='A' THEN nl;
  155.     IF ch='S' THEN cmd:=ExitAndSave;
  156.   END;
  157. END;
  158.  
  159.  
  160.  
  161.  
  162.  
  163. {$F+}
  164. VAR lx,ly:integer;
  165. PROCEDURE ShowWhere;
  166. { Procedure Called by GetKey (as the BeforeNext procedure) to display the
  167.   cursor position.  It must be activated (by ^KW) }
  168. VAR x,y:byte;
  169. BEGIN
  170.   IF (lx<>cx) OR (ly<>cy) THEN
  171.   BEGIN
  172.     IF Local THEN writescreen(cstr(cx)+':'+cstr(cy)+'  ',1,ScreenHeight-3,7)
  173.     ELSE
  174.     BEGIN
  175.       x:=wherex; y:=wherey;
  176.       statusline3(c0+cstr(cx)+':'+cstr(cy));
  177.       Gotoxy(x,y);
  178.     END;
  179.   END;
  180.   lx:=cx; ly:=cy;
  181. END;
  182. {$F-}
  183.  
  184. PROCEDURE DoToggleWhere;
  185. { Installs/uninstalls The ShowWhere procedure into the BeforeNext procedure }
  186. BEGIN
  187.   IF @BeforeNext=@DoNothing THEN
  188.   BEGIN
  189.     BeforeNext:=ShowWhere;
  190.     lx:=-1;
  191.   END
  192.   ELSE BEGIN
  193.     BeforeNext:=DoNothing;
  194.     StatusLine3(C0);
  195.   END;
  196. END;
  197.  
  198.  
  199. PROCEDURE Help;
  200. { Prints out the Help file and then causes a redisplay afterward }
  201.   PROCEDURE GotoP(x:integer);
  202.   BEGIN
  203.     gotoxy(20*((x-1) mod 4)+1,((x-1) div 4) +2);
  204.   END;
  205. VAR
  206.   ch:char;
  207.   x:integer;
  208.   top : integer;
  209.   s,topic : string;
  210.   fun : EdFun;
  211.   t:text;
  212.   topics : array[1..80] OF String[20];
  213.   nfound : integer;
  214. BEGIN
  215.   ansic('0');
  216.   assign(t,StartupDir+'WWIVEDIT.HLP');
  217.   topic:='';
  218.   nfound := 0;
  219.   {$I-} reset(t); {$I+}
  220.   IF IOResult=0 THEN
  221.   BEGIN
  222.     REPEAT
  223.       readln(t,s);
  224.     UNTIL s='START';
  225.     REPEAT
  226.       readln(t,s);
  227.       IF s<>'END' THEN BEGIN
  228.         inc(nfound);
  229.         topics[nfound]:=s;
  230.       END;
  231.     UNTIL s='END';
  232.     IF Local THEN
  233.     BEGIN
  234.       REPEAT
  235.         readln(t,s);
  236.       UNTIL s='LOCAL';
  237.       REPEAT
  238.         readln(t,s);
  239.         IF s<>'END' THEN BEGIN
  240.           inc(nfound);
  241.           Topics[nfound]:=s;
  242.         END;
  243.       UNTIL s='END'
  244.     END;
  245.   END;
  246.   top:=1;
  247.   IF Nfound<>0 THEN
  248.   REPEAT
  249.     clrscr;
  250.     Print(C5+'Available Help Topics: '+C2+'['+c1+'Press '+C5+'ESC'+C1+' to Exit, or '+
  251.           C5+'ENTER'+C1+' to Choose Topic'+C2+']');
  252.     FOR x:=1 TO Nfound DO
  253.     BEGIN
  254.       GotoP(x);
  255.       IF x=top
  256.         THEN ansic('4')
  257.         ELSE ansic('0');
  258.       prompt(Topics[x]);
  259.     END;
  260.     GotoP(top);
  261.     REPEAT
  262.       fun:=GetArrow;;
  263.       IF fun IN [Up,Down,Left,Right] THEN
  264.       BEGIN
  265.         ansic('0');
  266.         write(Topics[Top]);
  267.         CASE fun OF
  268.           Up   : Dec(Top,4);
  269.           Down : Inc(Top,4);
  270.           Left : Dec(Top);
  271.           Right: Inc(Top);
  272.         END;
  273.         IF Top<1 THEN Top:=Top+NFound
  274.         ELSE IF Top>NFound THEN Top:=Top-NFound;
  275.         GotoP(top);
  276.         ansic('4');
  277.         write(Topics[Top]);
  278.         GotoP(top);
  279.       END;
  280.     UNTIL Fun IN [Enter,NormalExit];
  281.     IF fun=NormalExit
  282.       THEN Topic:=''
  283.       ELSE Topic:=Topics[Top];
  284.     IF Fun=GetHelp THEN Topic:='HELP ON HELP';
  285.     Topic:=TransformString(Topic);
  286.     IF Topic<>'' THEN BEGIN
  287.       reset(t);
  288.       gotoxy(1,22);
  289.       prompt(C2+'Searching...');
  290.       REPEAT
  291.         readln(t,s);
  292.       UNTIL (s='EOF') OR (s=Topic+':') OR ((s=Topic+';') AND Local);
  293.       IF s='EOF' THEN print(C6+'Topic Not Found'+C0)
  294.       ELSE BEGIN
  295.         REPEAT
  296.           readln(t,s);
  297.         UNTIL s='SOT';
  298.         clrscr;
  299.         print(c7+'Topic '+c3+': '+c1+Topic);
  300.         REPEAT
  301.           readln(t,s);
  302.           IF s[length(s)]=^A THEN delete(s,length(s),1);
  303.           IF s[length(s)]=' ' THEN delete(s,length(s),1);
  304.           IF s='.P' THEN BEGIN
  305.             PauseScr;
  306.             ClrScr;
  307.           END
  308.           ELSE IF cmpleft(s,^B) THEN Center(RightS(s,Length(s)-1))
  309.           ELSE IF s<>'EOT' THEN
  310.             print(C0+s);
  311.         UNTIL (s='EOT') OR CheckAbort;
  312.       END;
  313.       close(t);
  314.     END;
  315.   UNTIL topic=''
  316.   ELSE BEGIN
  317.     print(c6+'Help file not found!'+c0);
  318.     prompt(c3+'Press any key to return to the editor.'+c0);
  319.     ch:=GetKey;
  320.   END;
  321.   ForcedRedisplay;
  322. END;
  323.  
  324.  
  325. PROCEDURE ForceDone;
  326. { Yell at the user for going over line limit }
  327. BEGIN
  328.   StatusLine1(c6+'No More Lines Left.'+chr(7)+c0);
  329. END;
  330.  
  331.  
  332.  
  333. PROCEDURE ReadInputFile(lines:integer; FileName:String);
  334. { Reads in an input file at the given line number }
  335. VAR t:text;
  336.   ccol:integer;
  337.   ch:char;
  338.   i:integer;
  339.   CurColor:char;
  340.   s:string;
  341.   f:file of byte;
  342.   BytesRead:LongInt;
  343.   Step : LongInt;
  344.   printed : integer;
  345. BEGIN
  346.   assign(t,Filename);
  347.   {$I-} reset(t); {$I+}
  348.   IF IOResult=0 THEN
  349.   BEGIN
  350.     BytesRead:=0;
  351.     assign(f,Filename);
  352.     reset(f);
  353.     Step := FileSize(f) DIV 20;
  354.     close(f);
  355.     curcolor:='0';
  356.     ccol:=1;
  357.     prompt(C2+'Loading File '+C3+': '+C0+dup('░',20)+ESC+'[20D');
  358.     Printed:=0;
  359.     ansic('1');
  360.     WHILE (NOT EOF(t)) AND (Lines<MaxLines) DO
  361.     BEGIN
  362.       Drain;
  363.       readln(t,s);
  364.       BytesRead:=BytesRead+Length(s)+1;
  365.       WHILE BytesRead DIV Step >= Printed DO
  366.       BEGIN
  367.         write('█');
  368.         inc(Printed);
  369.       END;
  370.       inc(lines);
  371.       ccol:=1;
  372.       CurColor:='0';
  373.       IF (s[length(s)]=^A) AND (s[length(s)-1]=' ') THEN
  374.         delete(s,length(s)-1,1);
  375.       WHILE s<>'' DO
  376.         IF NOT (s[1] IN [^A,^B,^C]) THEN
  377.         BEGIN
  378.           IF ccol>LineLen THEN BEGIN
  379.             inc(Lines);
  380.             Line[lines]^.HardCR:=False;
  381.             ccol:=1;
  382.           END;
  383.           Line[lines]^.l:=Line[lines]^.l+s[1];
  384.           Line[Lines]^.c:=Line[Lines]^.c+CurColor;
  385.           delete(s,1,1);
  386.           inc(ccol);
  387.         END
  388.         ELSE BEGIN
  389.           IF s[1]=^B THEN
  390.           BEGIN
  391.             IF ccol<>1 THEN BEGIN
  392.               Line[Lines]^.HardCr:=TRUE;
  393.               ccol:=1;
  394.               inc(Lines);
  395.             END;
  396.             Line[Lines]^.l:='/C:';
  397.             Line[Lines]^.c:='000';
  398.             delete(s,1,1);
  399.           END
  400.           ELSE IF s[1]=^C THEN
  401.           BEGIN
  402.             CurColor:=s[2];
  403.             delete(s,1,2);
  404.           END ELSE IF s[1]=^A THEN
  405.           BEGIN
  406.             Line[Lines]^.HardCR:=FALSE;
  407.             delete(s,1,1);
  408.           END;
  409.         END;
  410.     END;
  411.     close(t);
  412.     ansic('0');
  413.   END;
  414.   HighLine:=Lines;
  415. END;
  416.  
  417. FUNCTION CheckDest:boolean;
  418. VAR
  419.   t:text;
  420.   s:string;
  421.   ok, NeedOK:boolean;
  422. BEGIN
  423.   ok:=TRUE;
  424.   NeedOK:=false;
  425.   Assign(t,StartUpDir+'NOTAG');
  426.   {$I-} reset(t); {$I+}
  427.   IF IOResult=0 THEN
  428.   BEGIN
  429.     WHILE (NOT EOF(t)) AND OK DO
  430.     BEGIN
  431.       Readln(t,s);
  432.       IF s[1]='"' THEN BEGIN
  433.         Delete(s,1,1);
  434.         Delete(s,length(s),1)
  435.       END;
  436.       IF pos(s,Destination)>0 THEN ok:=FALSE;
  437.     END;
  438.     close(t);
  439.   END;
  440.   CheckDest:=OK;
  441. END;
  442.  
  443. PROCEDURE WriteOutputFile(VAR ReturnCode:integer);
  444. { Writes output file... could use some color optimizations }
  445. VAR
  446.   t, t1:text;
  447.   l,x,i:integer;
  448.   ch:char;
  449.   ccol : integer;
  450.   curcolor : char;
  451.   plural:string[1];
  452.   ignore : integer;
  453.   s,s1:string;
  454.   BBSTag:Text;
  455.   dummy : integer;
  456.   sr : SearchRec;
  457.   Nfound : integer;
  458. BEGIN
  459.   dummy:=returncode;
  460.   nfound :=0;
  461.   assign(t,Filename);
  462.   l:=MaxLines;
  463.   WHILE (l>0) AND (Line[l]^.l='') DO
  464.     dec(l);
  465.   s:=TransformString(Line[l]^.L);
  466.   IF (length(s)>2) AND (s='/ES') THEN
  467.      Delete(s,2,1);  { Remove the E }
  468.   IF s='/SN' THEN ReturnCode := NonAnonymousReturnCode
  469.   ELSE IF s='/SY' THEN ReturnCode := AnonymousReturnCode
  470.   ELSE ReturnCode:=NormalReturnCode;
  471.   IF cmpLeft(s,'/S') THEN dec(l);
  472.   IF l>1
  473.     THEN plural:='s'
  474.     ELSE plural:='';
  475.   IF l>0 THEN
  476.   BEGIN
  477.     nl;
  478.     s:=C7+'Saving '+C1+cstr(l)+C7+' line'+plural+'... '+C0;
  479.     IF OKTaglines
  480.       THEN OkTaglines:=OKTaglines AND CheckDest;
  481.     IF dummy=0
  482.       THEN prompt(s)
  483.       ELSE StatusLine3(s);
  484.     clreol;
  485.     CurColor:='0';
  486.     ignore:=0;
  487.     rewrite(t);
  488.     FOR x:=1 TO l DO
  489.     BEGIN
  490.       CurColor:='0';
  491.       s1:=Line[x]^.l;
  492.       s:=TransformString(s1);
  493.       IF (length(s)>1) AND (s[1]='/') THEN
  494.       BEGIN
  495.         IF cmpLeft(s,'/ES') OR cmpLeft(s,'/S') THEN
  496.         BEGIN
  497.           Line[x]^.l:='';
  498.           s1:='';
  499.         END
  500.         ELSE IF cmpLeft(s,'/C:') THEN
  501.         BEGIN
  502.           Delete(Line[x]^.c,1,3);
  503.           Insert('000',Line[x]^.c,1);
  504.         END;
  505.       END;
  506.       ccol:=1;
  507.       FOR i:=1 TO length(s1) DO
  508.         IF Color(Line[x]^,i)<>CurColor THEN
  509.         BEGIN
  510.           CurColor:=Color(Line[x]^,i);
  511.           insert(^C+CurColor,s1,ccol);
  512.           inc(ccol,3);
  513.         END ELSE inc(ccol);
  514.       IF cmpLefti(s1,'/C:') THEN
  515.       BEGIN
  516.         delete(s1,1,3);
  517.         insert(^B,s1,1);
  518.       END;
  519. {      IF NOT (Line[x]^.HardCR) AND (s1[length(s1)]<>' ') THEN
  520.         s1:=s1+' ';}
  521.       IF Line[x]^.HardCR
  522.         THEN writeln(t,s1)
  523.         ELSE writeln(t,s1+^A);
  524.     END;
  525.     IF curColor<>'0' THEN write(t,C0);
  526.     IF info.selected>3 THEN
  527.     BEGIN
  528.       info.selected:=3;
  529.       WHILE (info.selected>0) AND (info.Tagline[info.selected]<>'') DO
  530.         dec(info.selected);
  531.     END;
  532.     IF OkTagLines AND NOT FileThere AND
  533.        (info.selected>0) AND
  534.        (info.method<>0) AND (info.method<>6) AND
  535.        (info.Tagline[info.selected]<>'') AND
  536.        (ReturnCode <> AnonymousReturnCode)  THEN
  537.     BEGIN
  538.       prompt(C2+'Writing Personal Tag Line... '+C0);
  539.       FindFirst(StartupDir+'WWIVEDIT.DIV',0,sr);
  540.       IF DOSError<>0 THEN
  541.         writeln(t,'-----')
  542.       ELSE BEGIN
  543.         assign(t1,StartUpDir+'WWIVEDIT.DIV');
  544.         reset(t1);
  545.         readln(t1,s);
  546.         writeln(t,s);
  547.         close(t1);
  548.       END;
  549.       ccol:=1;
  550.       WHILE ccol<length(info.Tagline[1])-3 DO
  551.       BEGIN
  552.         IF copy(TransformString(info.Tagline[1]),ccol,3)='/C:' THEN
  553.         BEGIN
  554.           delete(info.Tagline[1],ccol,3);
  555.           insert(^B,info.Tagline[1],ccol);
  556.         END;
  557.         inc(ccol);
  558.       END;
  559.       ccol:=1;
  560.       FOR i:=1 TO Length(info.Tagline[info.selected]) DO
  561.       WITH info DO
  562.       BEGIN
  563.         IF TagLine[selected][i]=^M THEN
  564.         BEGIN
  565.           writeln(t);
  566.           ccol:=1;
  567.         END
  568.         ELSE IF TagLine[selected][i]=^N THEN
  569.         BEGIN
  570.           write(t,^H);
  571.           dec(ccol)
  572.         END
  573.         ELSE IF TagLine[selected][i] IN [^P,^C] THEN
  574.         BEGIN
  575.           write(t,^C);
  576.           CurColor:=TagLine[selected][i+1];
  577.           dec(ccol,1);
  578.         END ELSE IF TagLine[selected][i] IN [^B,#32..#255]-[#127] THEN
  579.         BEGIN
  580.           write(t,TagLine[selected][i]);
  581.           inc(ccol)
  582.         END
  583.       END;
  584.       IF ccol<>1 THEN writeln(t);
  585.     END;
  586.     IF AddBBSTag AND (NOT FileThere) AND CheckDest THEN
  587.     BEGIN
  588.       prompt(c5+'Writing BBS tagline... '+c0);
  589.       findfirst(StartupDir+'BBS*.TAG', 0, sr);
  590.       WHILE DOSError=0 DO
  591.       BEGIN
  592.         inc(nfound);
  593.         FindNext(sr);
  594.       END;
  595.       nfound:=random(nfound)+1;
  596.       findfirst(StartupDir+'BBS*.TAG', 0, sr);
  597.       dec(nfound);
  598.       WHILE nfound>0 DO
  599.       BEGIN
  600.         dec(nfound);
  601.         FindNext(sr);
  602.       END;
  603.       writeln(t);
  604.       assign(bbstag,StartupDir+sr.name);
  605.       reset(bbstag);
  606.       WHILE not EOF(bbsTag) DO
  607.       BEGIN
  608.         read(bbsTag,ch);
  609.         write(t,ch)
  610.       END;
  611.       close(bbstag);
  612.     END;
  613.     close(t);
  614.   END;
  615.   IF dummy<>0 THEN statusline3(C0);
  616.   IF (l=0) AND FileThere THEN BEGIN
  617.     nl;
  618.     clreol;
  619.     print(c2+'File erased'+C0);
  620.     erase(t);
  621.   END
  622.   ELSE IF l=0 THEN
  623.   BEGIN
  624.     nl;
  625.     clreol;
  626.     Print(c0+'Aborted');
  627.   END;
  628. END;
  629.  
  630.  
  631. PROCEDURE DoBackspace;
  632. { All this just because the user hits the Backspace (or Delete) }
  633. VAR
  634.   temp:LineType;
  635.   Ins:boolean;
  636. BEGIN
  637.   Ins:=InsertMode;                { Save the current InsertMode State }
  638.   InsertMode:=True;               { Set insert mode on }
  639.   IF cx > 1 THEN BEGIN            { If we aren't in the first column, things are easy }
  640.     LDelete(cy,cx-1,1);           { Just delete the character to the left of }
  641.     dec(cx);                      { the cursor and back up }
  642.     reformat(cy,false);
  643.   END
  644.   ELSE IF len(cy)=0 THEN BEGIN    { Special case for if there isn't anything }
  645.     DeleteLine(cy);               { On the line we are backspacing from }
  646.     dec(cy);
  647.     cx:=Len(cy)+1;
  648.   END
  649.   ELSE IF cy>1 THEN BEGIN         { Otherwise, the user wants to join two lines }
  650.     dec(cy);                      { Back up one line }
  651.     cx:=len(cy)+1;                { move to the end of it }
  652.     IF (cx=1) THEN
  653.       DeleteLine(cy)
  654.     ELSE BEGIN
  655.       Line[cy]^.hardCR:=false;
  656.       Reformat(cy,false);         { Reformat everything now to shorten the line }
  657.     END;
  658.   END;
  659.   InsertMode:=Ins;                { Go back to current insert state }
  660. END;
  661.  
  662.  
  663.  
  664.  
  665. PROCEDURE DoCenterLine(VAR cy:integer);
  666. { Places the centering code at the beginning of the line }
  667. VAR
  668.   Space:LineType;
  669.   ins : boolean;
  670. BEGIN
  671.   Ins:=InsertMode;
  672.   InsertMode:=true;
  673.   Space.l:='/C:';
  674.   Space.c:='000';
  675.  
  676.   IF (Len(cy)>0) AND (Len(cy)<LineLen-3) THEN
  677.     LInsert(Space,cy,1);
  678.  
  679.   cx:=1;
  680.   IF cy<MaxLines THEN inc(cy);
  681.   InsertMode:=ins;
  682. END;
  683.  
  684.  
  685.  
  686. PROCEDURE ShowBlockStatus;
  687. BEGIN
  688.   StatusLine3('Block Begin Line '+cstr(BlockStart)+', Block Ending Line '+cstr(BlockEnd));
  689.   AfterNext:=ClrStatLine3;
  690. END;
  691.  
  692.  
  693. PROCEDURE DoDeleteBlock(startline,endline:integer);
  694. VAR
  695.   i:integer;
  696. BEGIN
  697.   IF EndLine>=StartLine THEN
  698.   FOR i:=0 TO endline-startline DO
  699.     DeleteLine(Startline);
  700. END;
  701.  
  702. PROCEDURE DoBlockCopy(VAR startline,endline:integer; toline:integer);
  703. VAR
  704.   x:integer;
  705.   o : integer;
  706.   i : integer;
  707. BEGIN
  708.   IF (ToLine+EndLine-StartLine<MaxLines) AND (startline>0) AND
  709.      (startline<=endline) AND ((toline>endline) OR (toline<=startline)) THEN
  710.   FOR i:=0 TO EndLine-StartLine DO
  711.   BEGIN
  712.     InsertLine(toline,Line[i+StartLine]^);
  713.     inc(toline);
  714.   END;
  715. END;
  716.  
  717. PROCEDURE DoBlockMove(VAR BlockStart,BlockEnd:integer; ToLine:integer);
  718. VAR x:integer;
  719. BEGIN
  720.   x:=BlockStart;
  721.   IF ToLine>BlockStart
  722.     THEN x:=ToLine-BlockEnd+BlockStart-1
  723.     ELSE x:=ToLine;
  724.   DoBlockCopy(BlockStart,BlockEnd,ToLine);
  725.   DoDeleteBlock(BlockStart,BlockEnd);
  726.   BlockEnd:=x+BlockEnd-BlockStart;
  727.   BlockStart:=x;
  728.   ShowBlockStatus;
  729. END;
  730.  
  731. PROCEDURE DoInsertFile;
  732. { Prompt for a file name and then read it in at the end of the current
  733.   Text Buffer }
  734. VAR
  735.   s : string;
  736. BEGIN
  737.   StatusLine3(C2+'File Name read in > '+C1);
  738.   readln(s);
  739.   StatusLine3(C0);
  740.   IF s<>'' THEN ReadInputFile(HighLine,s);
  741.   StatusLine3('');
  742.   ShowHeader;
  743. END;
  744.  
  745.  
  746. PROCEDURE PrintOutput;
  747. { Prints the current text buffer to the screen }
  748. VAR
  749.   i, j, s : integer;
  750.   ccol : char;
  751.  
  752. BEGIN
  753.   clrscr;
  754.   ccol:='0';
  755.   ansic(ccol);
  756.   print(title);
  757.   i:=0;
  758.   WHILE i < Highline DO
  759.   BEGIN
  760.     inc(i);
  761.     IF cmpLeftI(Line[i]^.l,'/C:') THEN
  762.       Center(RightS(Line[i]^.l,len(i)-3))
  763.     ELSE
  764.     FOR j:=1 TO Len(i) DO
  765.     BEGIN
  766.       IF Line[i]^.c[j]<>ccol THEN BEGIN
  767.         ccol:=Line[i]^.c[j];
  768.         ansic(ccol);
  769.       END;
  770.       prompt(Line[i]^.l[j]);
  771.     END;
  772.     IF checkAbort THEN i:=HighLine;
  773.     writeln;
  774.     ccol:='0';
  775.     ansic('0');
  776.   END;
  777.   pausescr;
  778.   ForcedRedisplay;
  779. END;
  780.  
  781.  
  782. PROCEDURE DoSaveAndContinue;
  783. VAR dummy:integer;
  784. BEGIN
  785.   dummy:=-1;
  786.   WriteOutputFile(dummy);
  787. END;
  788.  
  789. PROCEDURE DoEnter;
  790. BEGIN
  791.   IF cx<=Len(cy) THEN
  792.   BEGIN
  793.     Line[0]^.l:=copy(Line[cy]^.l,cx,len(cy)-cx+1);
  794.     Line[0]^.c:=copy(Line[cy]^.c,cx,len(cy)-cx+1);
  795.     LDelete(cy,cx,len(cy)-cx+1);
  796.     inc(cy);
  797.     InsertLine(cy,Line[0]^);
  798.     InitLine(Line[0]^);
  799.     cx:=1;
  800.     Line[cy]^.HardCR:=Line[cy-1]^.hardCR;
  801.     Reformat(cy,false);
  802.   END
  803.   ELSE BEGIN
  804.     inc(cy);
  805.     cx:=1;
  806.     InitLine(Line[0]^);
  807.     InsertLine(cy,Line[0]^);
  808.   END;
  809.   Line[cy-1]^.HardCR := TRUE;
  810. END;
  811.  
  812.  
  813. PROCEDURE DoDelChar;
  814. BEGIN
  815.   inc(cx);
  816.   IF cx>Len(cy)+1 THEN
  817.   BEGIN
  818.     dec(cx);
  819.     IF Len(cy+1)=0 THEN
  820.       DeleteLine(cy+1)
  821.     ELSE BEGIN
  822.       Line[cy]^.HardCR:=False;
  823.       Reformat(cy,false);
  824.     END;
  825.   END
  826.   ELSE DoBackspace;
  827. END;
  828.  
  829. PROCEDURE DoTab;
  830. VAR
  831.   Temp : LineType;
  832. BEGIN
  833.   IF cx < LineLen - TabStop THEN
  834.   REPEAT
  835.     MakeString(temp,' ',CurrentColor);
  836.     LInsert(Temp,cy,cx);
  837.     Reformat(cy,False);
  838.     inc(cx);
  839.   UNTIL (cx-1) mod TabStop =0;
  840. END;
  841.  
  842. PROCEDURE DoToggleScreen;
  843. BEGIN
  844.   IF ScreenState=0 THEN BEGIN
  845.     ScreenState:=1;
  846.     WindowTop:=1;
  847.     WindowBottom:=ScreenHeight-3;
  848.   END
  849.   ELSE IF ScreenState=1 THEN BEGIN
  850.     ScreenState:=2;
  851.     WindowTop:=3;
  852.   END
  853.   ELSE BEGIN
  854.     ScreenState:=0;
  855.     WindowTop:=5;
  856.     WindowBottom:=ScreenHeight-4;
  857.   END;
  858.   WindowHeight:=WindowBottom-WindowTop;
  859.   ViewBottom:=ViewTop+WindowHeight;
  860.   ForcedRedisplay;
  861. END;
  862.  
  863. FUNCTION DoFun(fun:edfun; VAR ch:char):edfun;
  864. BEGIN
  865.   CASE fun OF
  866.     BackSpace   : IF ((cy=1) AND (cx>1)) OR (cy>1) THEN
  867.                     DoBackspace;
  868.     Bottom      : cy:=highline+1;
  869.     CenterLine  : DoCenterLine(cy);
  870.     CopyBlock   : DoBlockCopy(BlockStart,BlockEnd,cy);
  871.     DelChar     : DoDelChar;
  872.     DelEOL      : LDelete(cy,cx,len(cy)-cx+1);
  873.     DeleteBlock : BEGIN
  874.                     cy:=BlockStart;
  875.                     DoDeleteBlock(BlockStart,BlockEnd);
  876.                   END;
  877.     DelLine     : BEGIN cx:=1; DeleteLine(cy); END;
  878.     DelSOL      : BEGIN
  879.                     LDelete(cy,1,cx-1);
  880.                     cx:=1;
  881.                   END;
  882.     Down        : IF cy<MaxLines THEN inc(cy);
  883.     _end        : cx:=len(cy)+1;
  884.     Enter       : DoEnter;
  885.     EraseWordLeft:BEGIN
  886.                     WHILE (cx>1) AND (character(cy,cx-1)=' ') DO
  887.                       DoBackspace;
  888.                     WHILE (cx>1) AND (character(cy,cx-1)<>' ') DO
  889.                       DoBackspace;
  890.                   END;
  891.     Find        : DoSearch;
  892.     FindLast    : SearchLast;
  893.     GetHelp     : Help;
  894.     GoBack      : BEGIN
  895.                     fun:=InsertChar;
  896.                     ch:=^H;
  897.                   END;
  898.     Home        : cx:=1;
  899.     InsertFile  : DoInsertFile;
  900.     InsLine     : insertLine(cy,Line[0]^);
  901.     Jump        : DoJump;
  902.     Left        : BEGIN
  903.                     dec(cx);
  904.                     IF (cx=0) AND (cy>1) THEN
  905.                     BEGIN
  906.                       cx:=len(cy-1)+1;
  907.                       dec(cy)
  908.                     END
  909.                   END;
  910.     MarkEnd     : BEGIN BlockEnd   := cy; ShowBlockStatus END;
  911.     MarkStart   : BEGIN BlockStart := cy; ShowBlockStatus END;
  912.     MoveBlock   : DoBlockMove(BlockStart,BlockEnd,cy);
  913.     PgDn        : ScrollWindowDown;
  914.     PgUp        : ScrollWindowUp;
  915.     RedisplayAll: ForcedRedisplay;
  916.     Right       : BEGIN
  917.                     inc(cx);
  918.                     IF cx>LineLen+1 THEN
  919.                     BEGIN
  920.                       inc(cy);
  921.                       cx:=1
  922.                     END;
  923.                   END;
  924.     SaveAndContinue: DoSaveAndContinue;
  925.     ShowBlockStat:ShowBlockStatus;
  926.     Tab         : DoTab;
  927.     ToggleInsert: BEGIN InsertMode:=NOT InsertMode; ShowMaxLines; END;
  928.     ToggleFullScreen : DoToggleScreen;
  929.     ToggleWhere : DoToggleWhere;
  930.     Top         : cy:=1;
  931.     Up          : IF cy>1 THEN dec(cy);
  932.     WordLeft    : Cx:=GoLeft(Line[cy]^.l,cx);
  933.     WordRight   : cx:=GoRight(Line[cy]^.l,cx);
  934.     WWIVColor   : BEGIN
  935.                     ch:=GetKey;
  936.                     IF MCICommands AND (ch IN ['g'..'z','G'..'Z']) THEN
  937.                       fun:=InsertMCI
  938.                     ELSE
  939.                     IF colorRangeCheck THEN
  940.                       IF Cmap[ch] THEN
  941.                         CurrentColor:=ch
  942.                       ELSE
  943.                     ELSE CurrentColor:=ch;
  944.                   END;
  945.   END;
  946.   DoFun:=Fun;
  947. END;
  948.  
  949.  
  950. PROCEDURE DoSlash(VAR fun : Edfun);
  951. VAR
  952.   s:string;
  953.   dummy:char;
  954. BEGIN
  955.   s:=TransformString(Line[cy-1]^.l);
  956.   IF s='/HELP' THEN
  957.   BEGIN
  958.     DeleteLine(cy-1);
  959.     dec(cy);
  960.     Help;
  961.   END;
  962.   IF s='/CLR' THEN
  963.   BEGIN
  964.     FOR cy:=1 TO MaxLines DO
  965.       InitLine(Line[cy]^);
  966.     cy:=1;
  967.   END;
  968.   IF s='/RL' THEN
  969.   BEGIN
  970.     dec(cy,2);
  971.     DeleteLine(cy);
  972.     DeleteLine(cy);
  973.   END;
  974.   IF s='/LI' THEN
  975.   BEGIN
  976.     dec(cy);
  977.     DeleteLine(cy);
  978.     PrintOutput;
  979.   END;
  980.   IF (s='/TI') AND AllowTitleChange THEN
  981.   BEGIN
  982.     dec(cy);
  983.     DeleteLine(cy);
  984.     gotoxy(9,1);
  985.     ansic('1');
  986.     clreol;
  987.     input(s,60);
  988.     IF s<>''
  989.       THEN Title:=s
  990.       ELSE BEGIN gotoxy(9,1); ansic('1'); prompt(title); END;
  991.   END;
  992.   IF (s='/CHECK') OR (s='SPELL') THEN BEGIN
  993.     Dec(cy);
  994.     DeleteLine(cy);
  995.     SpellCheck;
  996.   END;
  997.   IF s='/RD' THEN BEGIN
  998.     dec(cy);
  999.     deleteLine(cy);
  1000.     Fun:=DoFun(RedisplayAll,dummy);
  1001.   END;
  1002.   IF (length(s)<=4) AND (cmpLeft(s,'/ES') OR cmpLeft(s,'/S')) THEN
  1003.     Fun:=QuietExitAndSave;
  1004.   IF s='/ABT' THEN Fun:=AbortPost;
  1005. END;
  1006.  
  1007.  
  1008.  
  1009. FUNCTION EditText:EdFun;
  1010. VAR
  1011.   ch :char;
  1012.   fun : edfun;
  1013.   temp : linetype;
  1014.   s : string;
  1015.  
  1016. BEGIN
  1017.   Highline:=MaxLines;
  1018.   WHILE (HighLine>0) AND (Len(HighLine)=0) DO
  1019.     dec(Highline);
  1020.   REPEAT
  1021.     IF (cy>HighLine) AND (Len(cy)>0) THEN
  1022.       HighLine:=cy;
  1023.     IF cy>MaxLines THEN BEGIN
  1024.       prompt(^G);
  1025.       cy:=MaxLines;
  1026.     END;
  1027.     IF highline+1=MaxLines THEN
  1028.       StatusLine3(c6+'One Line Left!'+c0);
  1029.     IF highline=MaxLines THEN
  1030.       ForceDone;
  1031.  
  1032.     fun:=GetFun(ch);
  1033.     fun:=DoFun(fun,ch);
  1034.  
  1035.     IF (Fun=Enter) AND (len(cy-1)>1) AND (character(cy-1,1)='/') THEN
  1036.       DoSlash(Fun);
  1037.  
  1038.     IF cy>MaxLines THEN cy:=MaxLines;
  1039.     IF (Fun=InsertChar) OR (Fun=InsertMCI) THEN
  1040.     BEGIN
  1041.       IF cx<=len(cy) THEN  { Strip off trailing blanks if they don't have a color }
  1042.         WHILE (character(cy,len(cy))=' ') AND (Color(line[cy]^,len(cy))='0') AND (len(cy)>cx) DO
  1043.           LDelete(cy,len(cy),1);
  1044.       IF Fun=InsertMCI THEN
  1045.       BEGIN
  1046.         MakeString(Temp,^C,CurrentColor);
  1047.         Linsert(Temp,cy,cx);
  1048.         Reformat(cy,true);
  1049.         inc(cx);
  1050.       END;
  1051.       MakeString(Temp,ch,CurrentColor);
  1052.       Linsert(Temp,cy,cx);         { Insert it                               }
  1053.       Reformat(cy,true);
  1054.       inc(cx);                     { move cursor right                       }
  1055.     END;
  1056.     IF cy>ViewBottom THEN          { "Scroll" the viewport down if needed    }
  1057.     BEGIN
  1058.       ViewTop:=cy-3;
  1059.       ViewBottom:=ViewTop+WindowHeight;
  1060.       IF ViewBottom>MaxLines THEN
  1061.       BEGIN
  1062.         ViewBottom:=MaxLines;
  1063.         ViewTop:=ViewBottom-WindowHeight;
  1064.       END;
  1065.     END;
  1066.     IF cy<ViewTop THEN             { "Scroll" the viewport up if needed      }
  1067.     BEGIN
  1068.       ViewBottom:=cy+3;
  1069.       ViewTop:=ViewBottom-WindowHeight;
  1070.       IF ViewTop<1 THEN
  1071.       BEGIN
  1072.         ViewTop:=1;
  1073.         ViewBottom:=ViewTop+WindowHeight;
  1074.       END;
  1075.     END;
  1076.     Drain;
  1077.     IF not KeyPressed THEN
  1078.       redisplay;                    { Redisplay Everything that has changed   }
  1079.   UNTIL (fun IN [AbortPost,ExitAndSave,NormalExit,QuietExitAndSave]);
  1080.   ReDisplay; { In case there are still keystrokes in the buffer [macro] }
  1081.   EditText:=Fun;
  1082. END;
  1083.  
  1084. PROCEDURE MakeFile(i:integer; title:string);
  1085. VAR t:text;
  1086. BEGIN
  1087.   IF NOT InDos THEN
  1088.   BEGIN
  1089.     assign(t,'RESULT.ED');
  1090.     rewrite(t);
  1091.     writeln(t,i);
  1092.     writeln(t,title);
  1093.     close(t);
  1094.   END;
  1095. END;
  1096.  
  1097.  
  1098. VAR
  1099.   Result : edfun;                { The Result of the Visual Edit }
  1100.   ReturnCode : integer;          { The number returned in RESULT.ED }
  1101.  
  1102. BEGIN { Main }
  1103. {$IFDEF OVERLAY}
  1104.   OvrInit('WWIVEdit.OVR');                                     Drain;
  1105. {$ENDIF}
  1106.   Initialize;                                                  Drain;
  1107. {$IFDEF DIRECTVIDEO}
  1108.   Translate := FALSE;
  1109. {$ENDIF}
  1110.   IF NoColor OR ForceAnsi THEN
  1111.     Translate:=TRUE;
  1112.   FindTitle(Title,Destination);  { Find title & Destination }  Drain;
  1113.   InitInfo;                                                    Drain;
  1114.   clrscr;                        { Clear the Screen }
  1115.   ReadInputFile(0,Filename);     { Read in the Input file }
  1116.   ShowHeader;                    { Show the message header }
  1117.   Redisplay;                     { Show the file - If one was read it }
  1118.   REPEAT
  1119.     ansic(CurrentColor);
  1120.     gotoxy(cx,cy+WindowTop-ViewTop); { Put the cursor in the right position }
  1121.     result := EditText;              { Do a visual Edit and get the result  }
  1122.   UNTIL Done(Result);                { True it the user saves or aborts     }
  1123.   IF Result=AbortPost THEN ClrScr;   { If the Sysop aborts it with ALT-A then clear the screen }
  1124.   IF Result = QuietExitAndSave THEN
  1125.     StatusLine1('');
  1126.   ReturnCode:=0;
  1127.   IF Result IN [ExitAndSave,QuietExitAndSave] THEN
  1128.   BEGIN
  1129.     WriteOutputFile(ReturnCode);
  1130.     MakeFile(Returncode, Title);
  1131.   END;
  1132.   nl;
  1133.   ansic('0'); clreol;
  1134.   SaveInfo;
  1135. END.  { Main }
  1136.  
  1137.  
  1138.